package com.shield.framework.security.auth;

import com.shield.framework.config.ShieldSecurityProperties;
import com.shield.framework.security.token.ShieldTokenService;
import com.shield.framework.security.token.ShieldTokenStore;
import com.shield.framework.utils.SecurityUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.core.result.R;
import net.dreamlu.mica.core.utils.WebUtil;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Duration;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @description: 成功、失败处理器
 * @Author Andy
 */
@Slf4j
@RequiredArgsConstructor
/*@Configuration(proxyBeanMethods = false)*/
public class ShieldAuthHandler extends AccessDeniedHandlerImpl implements AuthenticationSuccessHandler, AuthenticationFailureHandler, LogoutSuccessHandler {

    private final ShieldTokenService shieldTokenService;
    private final ShieldTokenStore shieldTokenStore;
    private final ShieldSecurityProperties properties;



    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) {
        if (response.isCommitted()) {
            return;
        }
        // 没有权限 403
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        WebUtil.renderJson(response, R.fail("没有权限访问"));
    }

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e){
        log.error(e.getMessage(), e);
        // 转换异常并且抛出给统一异常工具处理
      //  R.throwFail(SystemCode.FAILURE, e.getMessage());
        WebUtil.renderJson(response, R.fail(e.getMessage()));
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
        Map<String, Object> data = new HashMap<>(3);
        // 用户信息
        AuthUser authUser = SecurityUtil.getUser(authentication);
        ShieldSecurityProperties.JwtToken jwtToken = properties.getJwtToken();
        Date now = new Date();
        Duration expireTime = jwtToken.getExpireTime();
        String token = shieldTokenService.createToken(authUser, now, jwtToken.getExpireTime());
        // token 管理
        shieldTokenStore.save(request, authUser, token, expireTime);
        // 响应数据
        data.put("token", token);
        // 用户信息
        data.put("userInfo", authUser);
        // 响应用于加密的公钥
        data.put("publicKey", properties.getUserKeyPair().getPublicBase64());
        WebUtil.renderJson(response, data);
    }

    @Override
    public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) {

    }
}
